package com.yupi.yoj.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.yoj.common.ErrorCode;
import com.yupi.yoj.constant.CommonConstant;
import com.yupi.yoj.exception.ThrowUtils;
import com.yupi.yoj.model.dto.comment.CommentEsDTO;
import com.yupi.yoj.model.dto.comment.CommentQueryRequest;
import com.yupi.yoj.model.dto.question.QuestionEsDTO;
import com.yupi.yoj.model.entity.Comment;
import com.yupi.yoj.model.entity.Question;
import com.yupi.yoj.model.entity.User;
import com.yupi.yoj.model.vo.CommentVO;
import com.yupi.yoj.model.vo.QuestionVO;
import com.yupi.yoj.model.vo.UserVO;
import com.yupi.yoj.service.CommentService;
import com.yupi.yoj.mapper.CommentMapper;
import com.yupi.yoj.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 46411
* @description 针对表【comment(题目评论)】的数据库操作Service实现
* @createDate 2024-10-01 03:10:27
*/
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>
    implements CommentService{

    @Autowired
    UserService userService;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public void validComment(Comment comment, boolean b) {
        String content = comment.getContent();
        ThrowUtils.throwIf(content.isEmpty() || content.length() > 100, ErrorCode.PARAMS_ERROR, "评论内容不能超过100个字符");
    }

    @Override
    public CommentVO getCommentVO(Comment comment) {
        Long userid = comment.getUserid();
        ThrowUtils.throwIf(comment == null || userid == null, ErrorCode.PARAMS_ERROR);
        CommentVO commentVO = new CommentVO();
        BeanUtil.copyProperties(comment, commentVO);
        User user = userService.getById(userid);
        ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR);
        UserVO userVO = userService.getUserVO(user);
        commentVO.setUserVO(userVO);
        return commentVO;
    }

    @Override
    public List<CommentVO> getCommentVOList(List<Comment> comment) {
        ArrayList<CommentVO> commentVOS = new ArrayList<>();
        for (int i = 0; i < comment.size(); i++) {
            commentVOS.add(getCommentVO(comment.get(i)));
        }
        return commentVOS;
    }

    @Override
    public Page<Comment> searchFromEs(CommentQueryRequest commentQueryRequest) {
        Long id = commentQueryRequest.getId();
        Long questionid = commentQueryRequest.getQuestionid();
        String content = commentQueryRequest.getContent();

        String searchText = commentQueryRequest.getSearchText();

        // es 起始页为 0
        long current = commentQueryRequest.getCurrent() - 1;
        long pageSize = commentQueryRequest.getPageSize();
        String sortField = commentQueryRequest.getSortField();
        String sortOrder = commentQueryRequest.getSortOrder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 过滤
     //   boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));
        if (id != null && id > 0) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));
        }

        // 包含任何一个标签即可
//        if (CollUtil.isNotEmpty(orTagList)) {
//            BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();
//            for (String tag : orTagList) {
//                orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));
//            }
//            orTagBoolQueryBuilder.minimumShouldMatch(1);
//            boolQueryBuilder.filter(orTagBoolQueryBuilder);
//        }
        // 按关键词检索
        if (StringUtils.isNotBlank(searchText)) {
//            boolQueryBuilder.should(QueryBuilders.matchQuery("description", searchText));
            boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));
            boolQueryBuilder.minimumShouldMatch(1);
        }

        // 按内容检索
      /*  if (StringUtils.isNotBlank(content)) {
            boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));
            boolQueryBuilder.minimumShouldMatch(1);
        }*/
        // 排序
        SortBuilder<?> sortBuilder = SortBuilders.scoreSort();
        if (StringUtils.isNotBlank(sortField)) {
            sortBuilder = SortBuilders.fieldSort(sortField);
            sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);
        }
        // 分页
        PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);
        // 构造查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
                .withPageable(pageRequest).withSorts(sortBuilder).build();
        SearchHits<CommentEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, CommentEsDTO.class);
        Page<Comment> page = new Page<>();
        page.setTotal(searchHits.getTotalHits());
        List<Comment> resourceList = new ArrayList<>();
        // 查出结果后，从 db 获取最新动态数据（比如点赞数）
        if (searchHits.hasSearchHits()) {
            List<SearchHit<CommentEsDTO>> searchHitList = searchHits.getSearchHits();
            List<Long> commentIdList = searchHitList.stream().map(searchHit -> searchHit.getContent().getId())
                    .collect(Collectors.toList());
            List<Comment> commentList = baseMapper.selectBatchIds(commentIdList);
            if (commentList != null) {
                Map<Long, List<Comment>> idPostMap = commentList.stream().collect(Collectors.groupingBy(Comment::getId));
                commentIdList.forEach(commentId -> {
                    if (idPostMap.containsKey(commentId)) {
                        resourceList.add(idPostMap.get(commentId).get(0));
                    } else {
                        // 从 es 清空 db 已物理删除的数据
                        String delete = elasticsearchRestTemplate.delete(String.valueOf(commentId), CommentEsDTO.class);
                        System.out.println("delete comment "+ delete);
                    }
                });
            }
        }
        page.setRecords(resourceList);
        return page;
    }

    @Override
    public Page<CommentVO> getCommentVOPage(Page<Comment> commentPage, HttpServletRequest request) {
        List<Comment> commentList = commentPage.getRecords();
        Page<CommentVO> commentVOPage = new Page<>(commentPage.getCurrent(), commentPage.getSize(), commentPage.getTotal());
        if (CollUtil.isEmpty(commentList)) {
            return commentVOPage;
        }
        // 1. 关联查询用户信息
        Set<Long> userIdSet = commentList.stream().map(Comment::getUserid).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));
        // 2. 已登录，获取用户点赞、收藏状态
        Map<Long, Boolean> postIdHasThumbMap = new HashMap<>();
        Map<Long, Boolean> postIdHasFavourMap = new HashMap<>();
        User loginUser = userService.getLoginUserPermitNull(request);
        if (loginUser != null) {
            Set<Long> commentIdSet = commentList.stream().map(Comment::getId).collect(Collectors.toSet());
            loginUser = userService.getLoginUser(request);
            // 获取点赞
//            QueryWrapper<PostThumb> postThumbQueryWrapper = new QueryWrapper<>();
//            postThumbQueryWrapper.in("postId", postIdSet);
//            postThumbQueryWrapper.eq("userId", loginUser.getId());
//            List<PostThumb> postPostThumbList = postThumbMapper.selectList(postThumbQueryWrapper);
//            postPostThumbList.forEach(postPostThumb -> postIdHasThumbMap.put(postPostThumb.getPostId(), true));
            // 获取收藏
//            QueryWrapper<PostFavour> postFavourQueryWrapper = new QueryWrapper<>();
//            postFavourQueryWrapper.in("postId", postIdSet);
//            postFavourQueryWrapper.eq("userId", loginUser.getId());
//            List<PostFavour> postFavourList = postFavourMapper.selectList(postFavourQueryWrapper);
//            postFavourList.forEach(postFavour -> postIdHasFavourMap.put(postFavour.getPostId(), true));
        }
        // 填充信息
        List<CommentVO> commentVOList = commentList.stream().map(comment -> {
            CommentVO commentoVO = CommentVO.objToVo(comment);
            Long userId = comment.getUserid();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            commentoVO.setUserVO(userService.getUserVO(user));
           /* commentoVO.setThumbnum(postIdHasThumbMap.getOrDefault(post.getId(), false));
            commentoVO.setFavournum(postIdHasFavourMap.getOrDefault(post.getId(), false));*/
            return commentoVO;
        }).collect(Collectors.toList());
        commentVOPage.setRecords(commentVOList);
        return commentVOPage;
    }
}




